package com.xbongbong.pro.statistics.help;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CalendarUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.pro.bi.commons.filter.SrFilterHandler;
import com.xbongbong.pro.bi.commons.sql.SqlBuilderHandler;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.domain.entity.ChartLimitEntity;
import com.xbongbong.pro.enums.errorcodes.StatisticsServicesErrorCodeEnum;
import com.xbongbong.pro.statistic.enums.ChartLimitTypeEnum;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.pro.statistic.help.ChartResultHelp;
import com.xbongbong.pro.statistic.pojo.ChartFieldAttrPojo;
import com.xbongbong.pro.statistic.result.pojo.ChartResultPojo;
import com.xbongbong.pro.statistic.result.pojo.FieldAttrPojo;
import com.xbongbong.pro.statistic.service.ChartLimitService;
import com.xbongbong.saas.enums.BirthdayTypeEnum;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 图表渲染帮助类
 *
 * @ClassName DescribeTableHelper
 * @Author 梁鲁江
 * 创建时间 2022/9/20 15:14
 * 修改时间  2022/9/20 15:14
 **/
@Component
public class DescribeTableHelper {
    @Resource
    private ChartResultHelp chartResultHelp;
    @Resource
    private SrFilterHandler sRFilterHandler;
    @Resource
    private ChartLimitService chartLimitService;
    @Resource
    private InitSqlHelper initSqlHelper;
    public Logger LOG = LoggerFactory.getLogger(getClass());
    /**
     * 筛选条件处理常用和自定义动态
     * @param conditionJson  筛选和查询条件的合体
     * @param corpid
     * @param chartId
     * @throws XbbException
     */
    public void searchCondition(JSONArray conditionJson, String corpid, Long chartId) throws XbbException {
        if (CollectionsUtil.isNotEmpty(conditionJson)) {
            for (int i = 0; i < conditionJson.size(); i++) {
                JSONObject conditionObj = conditionJson.getJSONObject(i);
                // 常用
                if (Objects.equals(conditionObj.getString("symbol"), ConditionEnum.NORMAL.getSymbol())) {
                    Map<String, Long> normalFilterResultMap = chartResultHelp.handleNormalFilter(conditionObj);
                    Long startTimestamp = normalFilterResultMap.get("startTimestamp");
                    Long endTimestamp = normalFilterResultMap.get("endTimestamp");
                    if (Objects.isNull(startTimestamp) && Objects.isNull(endTimestamp)) {
                        continue;
                    }
                    if (Objects.isNull(startTimestamp)) {
                        // 转成小于等于
                        conditionObj.put("symbol", ConditionEnum.LESSEQUAL.getSymbol());
                        conditionObj.put("value", Arrays.asList(endTimestamp));
                    } else if (Objects.isNull(endTimestamp)) {
                        // 转成大于等于
                        conditionObj.put("symbol", ConditionEnum.GREATEREQUAL.getSymbol());
                        conditionObj.put("value", Arrays.asList(startTimestamp));
                    } else {
                        // 转成range
                        conditionObj.put("symbol", ConditionEnum.RANGE.getSymbol());
                        conditionObj.put("value", Arrays.asList(startTimestamp, endTimestamp));
                    }
                } else if (Objects.equals(conditionObj.getString("symbol"), ConditionEnum.CUSTOM.getSymbol())) {
                    // 自定义
                    JSONObject dynamicDate = conditionObj.getJSONObject("dynamicDate");
                    //前端每次切换筛选类型时，默认不给条件，这里需要兼容下空条件
                    //数据集合并master分支时，直接使用该部分，bug的逻辑已经数据集分支手动添加
                    if(Objects.nonNull(dynamicDate)) {
                        // 处理开始时间
                        Integer startType = dynamicDate.getInteger("startType");
                        Integer startWay = dynamicDate.getInteger("startWay");
                        Integer startTime = dynamicDate.getInteger("startTime");
                        Long startTimestamp = chartResultHelp.handleDynamicDate(startType, startWay, startTime, true);
                        // 处理结束时间
                        Integer endType = dynamicDate.getInteger("endType");
                        Integer endWay = dynamicDate.getInteger("endWay");
                        Integer endTime = dynamicDate.getInteger("endTime");
                        Long endTimestamp = chartResultHelp.handleDynamicDate(endType, endWay, endTime, false);
                        // 校验
                        if (Objects.nonNull(startTimestamp) && Objects.nonNull(endTimestamp)
                                && DateTimeUtil.differenceInDays(startTimestamp, endTimestamp) > TimeConstant.LEAP_YEAR) {
                            LOG.error("corpid:" + corpid + ",chartId:" + chartId + ",动态时间筛选超过一年");
                            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224078, StatisticsServicesErrorCodeEnum.API_ERROR_224078.getMsg(), ConditionEnum.CUSTOM.getMemo());
                        }
                        // 转成range
                        conditionObj.put("symbol", ConditionEnum.RANGE.getSymbol());
                        conditionObj.put("value", Arrays.asList(startTimestamp, endTimestamp));
                    }
                }
            }
        }
    }


    /**
     * 获取查询条件
     * @param chartEntity
     * @return
     * @throws XbbException
     */
    public String filterField(ChartEntity chartEntity) throws XbbException {
        JSONArray conditionJson = chartEntity.getFilter();
        conditionJson = JSON.parseArray(conditionJson.toJSONString());
        // 地图显示范围及钻取
        chartResultHelp.parseMap(chartEntity,conditionJson);
        JSONArray searchJson = chartEntity.getSearch();
        searchJson = JSON.parseArray(searchJson.toJSONString());
        initSqlHelper.funnelItemMark(chartEntity,conditionJson,searchJson);
        if (searchJson != null && searchJson.size() > 0) {
            conditionJson.addAll(searchJson);
        }
        // 筛选条件处理常用和自定义动态
        searchCondition(conditionJson, chartEntity.getCorpid(), chartEntity.getId());
        SqlBuilderHandler sqlBuilder =  SqlBuilderHandler.start();
        Map<String,StringBuffer> filterMap = Maps.newHashMap();
        sRFilterHandler.appendFilter(conditionJson,sqlBuilder,null,filterMap,true);
        return sqlBuilder.end().getSql();
    }

    /**
     * 统计表分页的限制
     * @param chartEntity
     * @param chartResultPojo
     * @param limit
     * @return
     */
    public int statisticsLimit(ChartEntity chartEntity, ChartResultPojo chartResultPojo, int limit) {
        //统计表的limit改为1000，因为原来es是1W,用户感知太明显
        if(chartLimitService.getChartLimtFlag(chartEntity.getCorpid(), RedisPrefixConstant.STATISTICS_TABLE_CK_LIMIT, ChartLimitTypeEnum.CHART_STATISTICS_TABLE_CK_LIMIT)){
            limit = chartLimitService.chartLimitNum(chartResultPojo.getCorpid(), ChartLimitTypeEnum.CHART_STATISTICS_TABLE_CK_LIMIT.getCode(), limit);
        }
        Boolean exportFlag = chartResultPojo.getExportFlag();
        if(exportFlag!=null && exportFlag){
            limit = chartLimitService.chartLimitNum(chartResultPojo.getCorpid(), ChartLimitTypeEnum.CHART_STATISTICS_TABLE_EXPORT_CK_LIMIT.getCode(), limit);
        }
        return limit;
    }

    public Map<String, Map<String, String>> getStringMapMap(ChartEntity chartEntity, Map<String, Map<String, String>> attrLinkMap, List<ChartFieldAttrPojo> linkAttrList) {
        List<ChartFieldAttrPojo> fieldAttrPojoList = new ArrayList<>();
        ChartTypeEnum chartTypeEnum = ChartTypeEnum.getByCode(chartEntity.getChartType());
        switch (chartTypeEnum) {
            case DATA_STATISTICS_TABLE:
                JSONArray colGroupAttr = chartEntity.getColGroupAttr();
                JSONArray rowGroupAttr = chartEntity.getRowGroupAttr();
                if (rowGroupAttr != null && rowGroupAttr.size() > 0) {
                    fieldAttrPojoList.addAll(JSONArray.parseArray(rowGroupAttr.toJSONString(), ChartFieldAttrPojo.class));
                }
                if (colGroupAttr != null && colGroupAttr.size() > 0) {
                    fieldAttrPojoList.addAll(JSONArray.parseArray(colGroupAttr.toJSONString(), ChartFieldAttrPojo.class));
                }
                break;
            case BAR_CHART:
            case LINE_CHART:
            case AREA_CHART:
            case RADAR_CHART:
            case PIE_CHART:
            case BIAXIAL_CHART:
            case BROADWISE_BAR_CHART:
            case SCATTER_CHART:
                JSONObject xAxisObject = chartEntity.getChartClassify().getJSONObject(0);
                ChartFieldAttrPojo xAxisAttr = JSONObject.parseObject(xAxisObject.toJSONString(), ChartFieldAttrPojo.class);
                fieldAttrPojoList.add(xAxisAttr);
                JSONArray chartSeriesArray = chartEntity.getChartSeries();
                if (chartSeriesArray != null && chartSeriesArray.size() > 0) {
                    JSONObject legendObject = chartSeriesArray.getJSONObject(0);
                    ChartFieldAttrPojo legendAttr = JSONObject.parseObject(legendObject.toJSONString(), ChartFieldAttrPojo.class);
                    fieldAttrPojoList.add(legendAttr);
                }
                break;
            case TARGET_CHART:
            case SECOND_TARGET_CHART:
                JSONArray targetRowGroupAttr = chartEntity.getRowGroupAttr();
                if(CollectionUtils.isNotEmpty(targetRowGroupAttr)){
                    List<ChartFieldAttrPojo> rowFieldAttrPojoList = JSONArray.parseArray(targetRowGroupAttr.toJSONString(), ChartFieldAttrPojo.class);
                    fieldAttrPojoList.addAll(rowFieldAttrPojoList);
                }
                break;
            default:
                break;
        }

        if (CollectionUtils.isEmpty(fieldAttrPojoList)) {
            return attrLinkMap;
        }
        for (ChartFieldAttrPojo fieldAttrPojo : fieldAttrPojoList) {
            Integer fieldType = fieldAttrPojo.getFieldType();
            if (Objects.equals(fieldType, FieldTypeEnum.LINK_BUSINESS_SINGLE.getType())
                    || Objects.equals(fieldType, FieldTypeEnum.LINK_RECEIVER.getType())) {
                linkAttrList.add(fieldAttrPojo);
            }
        }
        return attrLinkMap;
    }

    /**
     * 生日字段特殊处理
     *
     * @param fieldAttrPojo 字段属性
     * @param data          查询结果
     * @param attr          字段attr
     * @return 生日日期
     * @author zhouwq
     * @date 2019/6/3 17:34
     */
    public String getBirthday(FieldAttrPojo fieldAttrPojo, JSONObject data, String attr) {
        String value = "";
        String linkedText = fieldAttrPojo.getLinkedText();
        String dataValue = data.getString(attr);
        //判断是公历生日或农历生日
        if (Objects.equals(data.getInteger(linkedText), BirthdayTypeEnum.BIRTHDAY.getValue())) {
            value = dataValue;
        } else {
            if (dataValue != null) {
                value = CalendarUtil.lunar2Str(dataValue);
            }
        }
        return value;
    }
}
